package com.google.code.swingonfire.showcase.component.foldable;

import static com.google.code.swingonfire.builder.JComponentBuilders.*;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;

import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingConstants;
import javax.swing.event.ChangeEvent;

import com.google.code.eventsonfire.Events;
import com.google.code.eventsonfire.awt.AWTEvents;
import com.google.code.eventsonfire.swing.SwingEventHandler;
import com.google.code.eventsonfire.swing.SwingEvents;
import com.google.code.swingonfire.border.ShadowBorder;
import com.google.code.swingonfire.component.ButtonPanel;
import com.google.code.swingonfire.component.JBorderPanel;
import com.google.code.swingonfire.component.foldable.DefaultJFoldableTrigger;
import com.google.code.swingonfire.component.foldable.FoldableEvent;
import com.google.code.swingonfire.component.foldable.FoldableListener;
import com.google.code.swingonfire.component.foldable.JFoldablePanel;
import com.google.code.swingonfire.layout.GBC;
import com.google.code.swingonfire.showcase.TitlePanel;

public class JFoldablePanelShowcase extends JPanel implements FoldableListener
{

    private static final long serialVersionUID = 3954500189818433657L;

    private final JPanel panel;
    private final JFoldablePanel northPanel;
    private final JFoldablePanel southPanel;
    private final JFoldablePanel eastPanel;
    private final JFoldablePanel westPanel;

    private final JCheckBox animateBox;
    private final JCheckBox triggerMovingBox;
    private final JSlider durationSlider;

    public JFoldablePanelShowcase()
    {
        super(new BorderLayout());

        panel = new JPanel(new BorderLayout());

        DefaultJFoldableTrigger northTrigger = new DefaultJFoldableTrigger(new TriggerComponent());
        northTrigger.getIndicator().setPreferredSize(new Dimension(32, 32));
        northTrigger.setBackground(Color.WHITE);
        northTrigger.setOpaque(true);
        northPanel = new JFoldablePanel(new CheckerboardComponent(Color.ORANGE));
        northPanel.addFoldableListener(this);
        northPanel.setTriggerComponent(northTrigger);
        northPanel.setBackground(Color.WHITE);

        southPanel = new JFoldablePanel(new CheckerboardComponent(Color.ORANGE));
        southPanel.setDirection(SwingConstants.SOUTH);
        southPanel.addFoldableListener(this);

        eastPanel = new JFoldablePanel(new CheckerboardComponent(Color.ORANGE));
        eastPanel.setDirection(SwingConstants.EAST);
        eastPanel.addFoldableListener(this);

        westPanel = new JFoldablePanel(new CheckerboardComponent(Color.ORANGE));
        westPanel.setDirection(SwingConstants.WEST);
        westPanel.addFoldableListener(this);

        panel.add(new JBorderPanel(northPanel, ShadowBorder.create()), BorderLayout.NORTH);
        panel.add(new JBorderPanel(southPanel, ShadowBorder.create()), BorderLayout.SOUTH);
        panel.add(new JBorderPanel(eastPanel, ShadowBorder.create()), BorderLayout.EAST);
        panel.add(new JBorderPanel(westPanel, ShadowBorder.create()), BorderLayout.WEST);

        JPanel controlPanel =
            panelBuilder().layout(new BorderLayout()).background(Color.WHITE).opaque(true)
                .border(BorderFactory.createEmptyBorder(8, 12, 8, 12)).build();

        JPanel modifiersPanel = panelBuilder().layout(new GridBagLayout()).opaque(false).build();
        GBC gbc = new GBC(2, 5);

        animateBox =
            Events.bind(checkBoxBuilder().text("Perform animation").listener("animate", AWTEvents.fireOnAction())
                .opaque(false).selected(true).build(), this);
        modifiersPanel.add(labelBuilder().text("Animate:").labelFor(animateBox).build(), gbc.right());
        modifiersPanel.add(animateBox, gbc.next().hFill().weight(1));

        triggerMovingBox =
            Events.bind(
                checkBoxBuilder().text("Trigger moves with foldable")
                    .listener("triggerMoving", AWTEvents.fireOnAction()).opaque(false).selected(false).build(), this);
        modifiersPanel.add(labelBuilder().text("Trigger:").labelFor(triggerMovingBox).build(), gbc.next().right());
        modifiersPanel.add(triggerMovingBox, gbc.next().hFill().weight(1));

        durationSlider =
            Events.bind(
                sliderBuilder().minimum(0).maximum(250).value(25).label(0, String.format("%,.1f s", 0.0))
                    .label(50, String.format("%,.1f s", 0.50)).label(100, String.format("%,.1f s", 1.00))
                    .label(200, String.format("%,.1f s", 2.0)).label(150, String.format("%,.1f s", 1.5))
                    .label(250, String.format("%,.1f s", 2.5)).majorTickSpacing(25).minorTickSpacing(5)
                    .snapToTicks(true).listener(SwingEvents.fireOnChange("duration")).opaque(false).build(), this);

        modifiersPanel.add(labelBuilder().text("Duration:").labelFor(durationSlider).build(), gbc.next().right());
        modifiersPanel.add(durationSlider, gbc.next().hFill().weight(1));

        controlPanel.add(new ButtonPanel().right(Events.bind(
            buttonBuilder().text("Fold All").listener("foldAll", AWTEvents.fireOnAction()).build(), this), Events.bind(
            buttonBuilder().text("Unfold All").listener("unfoldAll", AWTEvents.fireOnAction()).build(), this)),
            BorderLayout.SOUTH);
        controlPanel.add(modifiersPanel, BorderLayout.CENTER);

        panel.add(new JBorderPanel(controlPanel, ShadowBorder.create(), true), BorderLayout.CENTER);

        add(new JBorderPanel(new TitlePanel("JFoldablePanel", "A panel, that can be triggered to be visible or not."),
            ShadowBorder.create()), BorderLayout.NORTH);
        add(panel, BorderLayout.CENTER);
    }

    @Override
    public void foldingInProgress(FoldableEvent event)
    {
        validate();
        repaint();
    }

    @SwingEventHandler(event = ActionEvent.class, eachTag = "foldAll")
    public void onFoldAll()
    {
        northPanel.setFolded(true);
        southPanel.setFolded(true);
        eastPanel.setFolded(true);
        westPanel.setFolded(true);
    }

    @SwingEventHandler(event = ActionEvent.class, eachTag = "unfoldAll")
    public void onUnfoldAll()
    {
        northPanel.setFolded(false);
        southPanel.setFolded(false);
        eastPanel.setFolded(false);
        westPanel.setFolded(false);
    }

    @SwingEventHandler(event = ActionEvent.class, eachTag = "animate")
    public void onAnimate()
    {
        boolean animate = animateBox.isSelected();

        northPanel.setAnimate(animate);
        southPanel.setAnimate(animate);
        eastPanel.setAnimate(animate);
        westPanel.setAnimate(animate);
    }

    @SwingEventHandler(event = ActionEvent.class, eachTag = "triggerMoving")
    public void onTriggerMoving()
    {
        boolean triggerMoving = triggerMovingBox.isSelected();

        northPanel.setTriggerMoving(triggerMoving);
        southPanel.setTriggerMoving(triggerMoving);
        eastPanel.setTriggerMoving(triggerMoving);
        westPanel.setTriggerMoving(triggerMoving);

        validate();
        repaint();
    }

    @SwingEventHandler(event = ChangeEvent.class, eachTag = "duration")
    public void onDuration()
    {
        double duration = durationSlider.getValue() / 100d;

        northPanel.setDuration(duration);
        southPanel.setDuration(duration);
        eastPanel.setDuration(duration);
        westPanel.setDuration(duration);
    }

}
